/*
 * dur_hmm_markov.h
 *
 *  Created on: Sep 20, 2011
 *      Author: tqlong
 */

#ifndef DUR_HMM_MARKOV_H_
#define DUR_HMM_MARKOV_H_

#include "dur_hmm.h"

class DurationHMMMarkov : public DurationHMM
{
public:
  typedef std::vector<int> sequence_t;
  typedef std::map<int, double> duration_prob_t;
  typedef std::vector<duration_prob_t> dpvec_t;
  typedef std::vector<arma::mat> emis_vec_t;
  typedef DiscreteHMM::joint_seq_t joint_seq_t;
  typedef struct Variables {
    arma::mat alpha, beta;
    arma::mat alphaS, betaS;
    arma::vec ACC_start;
    arma::mat ACC_trans, ACC_emis;
    dpvec_t ACC_dprob;
    emis_vec_t ACC_m_emis;
  } variable_t;
  typedef std::vector<sequence_t> vseq_t;
  typedef duration_prob_t::value_type& pair_dprob_t;
  typedef const duration_prob_t::value_type& const_pair_dprob_t;
public:
  void load(const char* fileName);
  void save(const char* fileName);

  void rand();
  void generate(int T, joint_seq_t &seq);

  double seq_probability(const sequence_t& o);
  double seq_probability_reverse(const sequence_t& o);

  void map(joint_seq_t& seq);

  void train(const vseq_t& data);
  double diff(DurationHMMMarkov& hmm);

  void print_params() const;
public:
  emis_vec_t m_emis_;  // markov emission
  variable_t var_;
protected:
  void compute_alpha(const sequence_t& o, variable_t& var);
  void compute_beta(const sequence_t& o, variable_t& var);
  void compute_alphaS(const sequence_t& o, variable_t& var);
  void compute_betaS(const sequence_t& o, variable_t& var);

  double subseq_prob(const sequence_t& o, int start, int len, int state);

  void accumulate(const sequence_t& o, double weight);
  void reestimate();
};

#endif /* DUR_HMM_MARKOV_H_ */
